package com.macro.mall.es.service.impl;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.macro.mall.es.dto.EsIndexDto;
import com.macro.mall.es.service.EsIndexService;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
import org.elasticsearch.action.admin.indices.get.GetIndexResponse;
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.GetMappingsRequest;
import org.elasticsearch.client.indices.GetMappingsResponse;
import org.elasticsearch.cluster.metadata.MappingMetaData;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Map;

@Service
@Slf4j
public class EsIndexServiceImpl implements EsIndexService {
    @Autowired
    private RestHighLevelClient restHighLevelClient;
    @Autowired
    private static final String INDEX_NAME = "project";


    @Override
    public void createIndex(EsIndexDto esIndexDto) {
        //检查索引是否已存在
        if (indexExists(esIndexDto.getIndexName())) {
            throw new RuntimeException("索引已存在");
        }
        //创建索引请求
        CreateIndexRequest indexRequest = new CreateIndexRequest(esIndexDto.getIndexName());
        //设置索引配置
        if (StringUtils.isNotBlank(esIndexDto.getIndexMapper())) {
            indexRequest.settings(esIndexDto.getIndexMapper(), XContentType.JSON);
        }
        //执行创建索引操作
        try {
            restHighLevelClient.indices().create(indexRequest, RequestOptions.DEFAULT);
            log.info("索引创建成功：" + esIndexDto.getIndexName());
        } catch (IOException e) {
            log.info("索引创建失败，失败信息：{}", e.getMessage());
            throw new RuntimeException("创建索引失败，失败信息：" + e.getMessage());
        }


    }

    @Override
    public boolean indexExists(String indexName) {
        try {
            GetIndexRequest getIndexRequest = new GetIndexRequest();
            //设置要检查的索引名称
            getIndexRequest.indices(indexName);

            getIndexRequest.indicesOptions(IndicesOptions.lenientExpandOpen());
            //执行请求
            GetIndexResponse getIndexResponse = restHighLevelClient.indices().get(getIndexRequest, RequestOptions.DEFAULT);
            //检查响应中的索引是否为空
            return getIndexResponse.getIndices().length > 0;
        } catch (IOException e) {
            //处理异常
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public void deleteIndex(String indexName) {
        //检查索引对象是否存在
        if (!indexExists(indexName)) {
            throw new RuntimeException("索引对象已存在");
        }
        try {
            restHighLevelClient.indices().delete(new DeleteIndexRequest(indexName), RequestOptions.DEFAULT);
            log.info("索引删除成功：" + indexName);
        } catch (IOException e) {
            log.error("索引删除失败：{},", e.getMessage());
            throw new RuntimeException("索引删除失败：" + indexName, e);
        }
    }

    @Override
    public Map<String, Object> getIndex(String indexName) {
        // 检查索引是否存在
        if (!indexExists(indexName)) {
            throw new RuntimeException("索引不存在：");
        }
        // 创建获取索引映射的请求
        GetMappingsRequest getMappingsRequest = new GetMappingsRequest().indices(indexName);
        // 执行获取索引映射操作
        try {
            GetMappingsResponse mappingsResponse = restHighLevelClient.indices().getMapping(getMappingsRequest, RequestOptions.DEFAULT);
            // 获取索引映射信息
            Map<String, MappingMetaData> mappings = mappingsResponse.mappings();
            log.info("获取索引映射成功：{}", indexName);
            // 将 MappingMetaData 转换为 Map<String, Object>
            Map<String, Object> indexMapping = mappings.get(indexName).getSourceAsMap();
            // 返回指定索引的映射信息
            return indexMapping;
        } catch (IOException e) {
            log.error("获取索引映射失败：{}", e.getMessage());
            throw new RuntimeException("获取索引映射失败：" + indexName, e);
        }
    }

    @Override
    public void updateIndex(EsIndexDto esIndexDto) {
        // 检查索引是否存在
        if (!indexExists(esIndexDto.getIndexName())) {
            throw new RuntimeException("索引不存在：" + esIndexDto.getIndexName());
        }
        //创建更新索引设置请求
        UpdateSettingsRequest updateSettingsRequest = new UpdateSettingsRequest(esIndexDto.getIndexName());
        //更新索引配置
        if (StringUtils.isNotBlank(esIndexDto.getIndexMapper())) {
            updateSettingsRequest.settings(esIndexDto.getIndexMapper(), XContentType.JSON);
        }
        //执行更新索引设置
        try {
            boolean acknowledged = restHighLevelClient.indices().putSettings(updateSettingsRequest, RequestOptions.DEFAULT).isAcknowledged();
            if (acknowledged) {
                log.info("索引设置更新成功：{}", esIndexDto.getIndexName());
            } else {
                log.warn("索引设置更新未被确认：{}", esIndexDto.getIndexName());
            }
        } catch (IOException e) {
            log.error("更新索引设置失败，错误信息：{}", e.getMessage());
            throw new RuntimeException("更新索引设置失败，错误信息：{}" + esIndexDto.getIndexName(), e);
        }
    }

    @Override
    public void search(EsIndexDto esIndexDto) {
        //创建 索引请求对象
        IndexRequest indexRequest = new IndexRequest(INDEX_NAME);
        //创建 查询请求对象
        SearchRequest searchRequest = new SearchRequest();
        //创建 条件查询构造器
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //创建 多条件拼接对象
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //开始条件拼接
        if (StringUtils.isNotBlank("product")) {
            boolQueryBuilder.must(QueryBuilders.matchQuery("product", "esIndexDto.getProduct()"));
        }
        //把 多条件拼接对象 给 条件查询构造器
        searchSourceBuilder.query(boolQueryBuilder);
        //分页
        searchSourceBuilder.from();
        searchSourceBuilder.size();
        //排序
        searchSourceBuilder.sort("publishTime", SortOrder.DESC);
        //把 条件查询构造器 给 查询请求对象
        searchRequest.source(searchSourceBuilder);
        //高亮
    }
}
